Tools Plus’s event modifier field provides information identical to that obtained directly from the Macintosh’s Event Manager. To reiterate, the Modifiers field of the event record contains information about the position of the Caps Lock, Shift, Option, Command and Control keys at the time of the event, as well as the position of the mouse button. This can be used, for example, to detect if the Command key was down when a key was typed (i.e. a Command-key sequence). In effect, your application could respond to command key sequences that are not menu equivalents by using this method. Your application could also place special significance on Option-Clicks. The most common use, however, is Shift-Tab that indicates that the user wants to tab to the previous field.
In the Macintosh’s Event Manager, the Modifiers field of the event record is an integer. Several of the bits indicate the state of the various modifiers, as detailed in Inside Macintosh Vol 1 and Vol 5. Tools Plus goes a step further and automatically decodes individual modifiers in the field. This is handled through a union in C, and a variant record in Pascal.
Event Modifiers Using C
```````````````````````
When programming in C, Tools Plus’s Modifiers structure is a union that lets you access both the integer obtained from the Macintosh’s Event Manager, as well as the individual flags (bits) within the integer. Tools Plus’s Modifiers structure looks like this:
union TPModifiersRec { /*This variable record contains */
/* an event's "modifiers" in 2 */
/* formats… */
/* • Macintosh Event: */
short Num; /* integer (bit operations */
/* required) */
/* • Modifier integer parsed */
struct { /* into components: */
unsigned short bit15 :1; /* (reserved bit) */
unsigned short bit14 :1; /* (reserved bit) */
unsigned short bit13 :1; /* (reserved bit) */
unsigned short ControlKey :1; /* Control key was down at event */
unsigned short OptionKey :1; /* Option key was down at event */
unsigned short CapsLock :1; /* Caps Lock was down at event */
unsigned short ShiftKey :1; /* Shift key was down at event */
unsigned short CmdKey :1; /* Command key was down at event */
unsigned short MouseUp :1; /* Mouse button was UP at event */
unsigned short bit6 :1; /* (reserved bit) */
unsigned short bit5 :1; /* (reserved bit) */
unsigned short bit4 :1; /* (reserved bit) */
unsigned short bit3 :1; /* (reserved bit) */
unsigned short bit2 :1; /* (reserved bit) */
unsigned short bit1 :1; /* (reserved bit) */
unsigned short bit0 :1; /* (reserved bit) */
} Bits; /* */
};
typedef union TPModifiersRec TPModifiersRec;
Whenever you access any of the individual modifier flags, you reference the “bits” part of the structure. For example, if you want to check if the Command key was down and the Option key was up when a key was typed, you can use an expression such as this:
if ((Poll.Modifiers.Bits.CmdKey) && (!Poll.Modifiers.Bits.OptionKey))
In contrast, the Modifiers field provided by the Macintosh’s Event Manager requires bitwise “And” operations to determine if a bit is set or not, thereby resulting in source code that looks more cryptic. The following line duplicates the previous example’s functionality using bitwise “And” operations instead of the available bits:
if ((Poll.Modifiers.Num & cmdKey) && !(Poll.Modifiers.Num & optionKey))
When you are working with the Modifiers structure, you may perform operations exclusively on the integer variant of the structure, on the bits variant, or if you choose, you can mix and match as needed. Several constants representing the “bit-equivalents” for the various flags contained in the Modifiers integer are available as follows:
/*Modifier masks */
#define btnState 0x0080 /*set to 1 if mouse button is up */
#define cmdKey 0x0100 /*set to 1 if Command key is down */
#define shiftKey 0x0200 /*set to 1 if Shift key is down */
#define alphaLock 0x0400 /*set to 1 if the Caps Lock key is down */
#define optionKey 0x0800 /*set to 1 if the option key is down */
#define controlKey 0x1000 /*set to 1 if the control key is down */
Event Modifiers Using Pascal
````````````````````````````
When programming in Pascal, Tools Plus’s Modifiers structure is a variant record that lets you access both the integer obtained from the Macintosh’s Event Manager, as well as the individual flags (bits) within the integer. Tools Plus’s Modifiers record looks like this:
{= Polling record's "event modifiers" info}
TPModifiersRec = packed record {This variable record contains }
{ an event's "modifiers" in 2 }
case integer of { formats… }
0: ( { • Macintosh Event: }
Num: integer { integer (bit operations }
); { required) }
1: ( { • Modifier integer parsed }
{ into components: }
bit15, bit14, bit13: boolean; { (reserved bits) }
ControlKey: boolean; { Control key was down at event }
OptionKey: boolean; { Option key was down at event }
CapsLock: boolean; { Caps Lock was down at event }
ShiftKey: boolean; { Shift key was down at event }
CmdKey: boolean; { Command key was down at event }
MouseUp: boolean; { Mouse button was UP at event }
bit6, bit5, bit4, bit3, bit2, { (reserved bits) }
bit1,bit0: boolean; { }
); { }
end;
You use each field in the record as an individual modifier variable. For example, if you want to check if the Command key was down and the Option key was up when a key was typed, you can use an expression such as this:
if Poll.Modifiers.CmdKey and not Poll.Modifiers.OptionKey then
In contrast, the Modifiers field provided by the Macintosh’s Event Manager requires bitwise “And” operations to determine if a bit is set or not, thereby resulting in source code that looks more cryptic. The following line duplicates the previous example’s functionality using bitwise “And” operations instead of the available bits:
if (BitAnd(Poll.Modifiers.Num,cmdKey) <> 0) and
BitAnd(Poll.Modifiers.Num,optionKey) = 0) then
When you are working with the Modifiers record, you may perform operations exclusively on the integer variant of the record, on the bits variant, or if you choose, you can mix and match as needed. Several constants representing the “bit-equivalents” for the various flags contained in the Modifiers integer are available as follows:
CONST {Modifier masks }
btnState =$0080; {set to 1 if mouse button is up }
cmdKey =$0100; {set to 1 if Command key is down }
shiftKey =$0200; {set to 1 if Shift key is down }
alphaLock =$0400; {set to 1 if the Caps Lock key is down }
optionKey =$0800; {set to 1 if the option key is down }
controlKey=$1000; {set to 1 if the control key is down }
Determine if an event occurred, and obtain that event. PollSystem also keeps Tools Plus’s automatic processes running.
pascal Boolean PollSystem (TPPollRecord *Poll);
function PollSystem(var Poll:TPPollRecord): BOOLEAN;
The Poll record contains all the information about an event.
The function’s value returns true if an event was obtained, and false if an event was not obtained. When PollSystem returns false, it is called a “null” event, or in Tools Plus terminology, a doNothing event.
PollSystem calls the Macintosh Event Manager’s WaitNextEvent function (or GetNextEvent function) which performs all necessary task switching and background processing control. Desk Accessories’ get their events, and other applications that are also running under MultiFinder or System 7 get some processing time.
If your application does “background processing,” that is, it performs an on-going process while it is waiting for events, it should perform “one cycle” of its background process each time it receives a doNothing event (when PollSystem returns false). A single cycle of your application’s background process should take no longer than 1/60 of a second. See the SetNullTime routine to set the interval at which your application receives doNothing events.
PollSystem should be called as often as possible (at least sixty times per second) to keep desk accessories, automatic processes, and other applications running under MultiFinder or System 7 running smoothly. It is important that your application does not do a lot of processing between calls to PollSystem or it will be a “CPU hog” and make other applications run sluggishly or in spurts and jumps.
Also see: SetNullTime.
Note: Your application should call PollSystem as often as possible (at
least 60 times per second) to allow other applications adequate
processing time.
Warning: Do not call PollSystem from within a BeginUpdateScreen /
EndUpdateScreen structure.
Tools Plus Event Codes
``````````````````````
Each event reported by PollSystem is identified by the first field of the polling record, Poll.What. The Poll.What field contains an event code that tells your application what to do with the event record’s information. Constants are used to identify event codes as follows:
CONST {Tools Plus event codes }
doNothing = 0; {no event }
doChgWindow = 1; {user clicked in an inactive window }
doRefresh = 2; {a window has to be refreshed }
doGoAway = 3; {the Go-Away box was clicked }
doButton = 4; {button was clicked }
doMenu = 5; {menu was selected }
doKeyDown = 6; {a keyboard key was pressed }
doAutoKey = 7; {a keyboard key is auto-repeating }
doKeyUp = 8; {a keyboard key was released }
doClickField = 9; {mouse clicked in inactive editing field}
doScrollBar = 10; {mouse clicked in a scroll bar }
doListBox = 11; {some sort of List Box activity }
doClick = 12; {mouse click/drag [1..3] }
doPopUpMenu = 13; {pop-up menu was selected }
doPictButton = 14; {picture button activity }
doClickControl=101; {mouse clicked in a custom control }
doManualEvent =102; {manually processed events }
doMoveWindow =103; {a window was moved by user }
doGrowWindow =104; {a window was “grown” by user }
doClickDesk =105; {mouse clicked in the desk top }
doZoomWindow =106; {zoom box was clicked by user }
doSuspend =107; {appl. suspended (in background) }
doResume =108; {appl. resumed (now active appl.) }
Event codes over 100 will likely be ignored by most applications. All events are detailed later, telling you how to respond to the event and which fields in the event record contain valid information that is related to the event.
What Does PollSystem Do?
````````````````````````
On the surface, it appears that PollSystem is just a fancy way to get an event from the Toolbox Event Manager. Quite to the contrary, PollSystem does a lot of work for you.
The biggest service that PollSystem performs is to keep Tools Plus’s automatic processes running smoothly. To do this, you must understand the difference between an internally processed event, and an externally processed event.
Internally Processed Events
```````````````````````````
An internal event is something that can be processed by Tools Plus without the knowledge or assistance of your application. Hence the term internal means internal to Tools Plus. The internal processing of events is how PollSystem drives its automatic tasks.
An example of an internally processed event is a key-down event from the Toolbox Event Manager. If the active window belongs to your application and it has an active editing field, the user’s key-strokes will affect the text in the editing field automatically. Since this event is processed internally, no event is reported to your application.
One of the tricks that PollSystem utilizes, is to process as many internal events as it possibly can before returning to your application. It will return to your application when the event queue is empty, or when it encounters an event that cannot be processed internally. Why doesn’t it process just one event at a time? If your application is busy and the user types 10 characters on the keyboard before PollSystem is called, the single call to PollSystem will process all 10 keystrokes! This ensures that Tools Plus’s automatic processes occur as smoothly as possible without accumulating a backlog of events.
Externally Processed Events
```````````````````````````
Whenever PollSystem encounters an event it cannot process internally, it reports the event to your application. An example of this is when the user clicks the close box in the active window. Your application may want to ask the user if he wants to save the changes before closing the document. Therefore, PollSystem only reports a request to close a window, and does not actually close it.
Some events may be ignored by your application. One of these events tells your application that the user dragged a window. Your application may be interested in a window’s co-ordinates at any given time, in which case this event would be crucial. In most cases, applications don’t care if the window is dragged, and always ignore the event.
Inside PollSystem
`````````````````
Inside PollSystem describes the inner workings of the PollSystem routine. Those programmers who are curious about this aspect, or those that want to know how Toolbox Events are translated into Tools Plus events may find this passage interesting.
Every time your application calls PollSystem, several things happen automatically:
(1) Desk accessories and background processes are given some processing time.
(2) The active desk accessory (if there is one) gets any events it requires.
(3) The insertion point is kept blinking in the active editing field (if there is one).
(4) Task switching occurs to give other applications some processing time (when using MultiFinder or System 7).
(5) The event queue is checked for an event. If any events exist, the first one is removed from the queue. If the event can be processed internally by Tools Plus, it is and this step is repeated.
(6) If an event is obtained that can not be processed internally by Tools Plus, then Tools Plus’s event record is populated with all the required information for that event in a format that is readily usable by your application.
(7) The cursor’s position is checked and its shape is changed if required.
(8) PollSystem returns to your application with an event, or a “no event” (false) status.
Translating Toolbox events to Tools Plus events
```````````````````````````````````````````````
Step 3 looks pretty simple when it is summarized in a couple lines, however, the recognition and processing of internal events is quite an extensive duty for Tools Plus. The table below describes this formidable task by listing the Macintosh’s Toolbox Event Manager’s event, the internal processes that follow, and the event that finally reaches your application. Remember that some Toolbox events are processed internally and never reach your application, and some events that reach your program can be ignored.
When PollSystem returns with a value of false, it indicates that no event has occurred. This is commonly called a “null event” or a doNothing event in Tools Plus. Usually, your application won’t do anything other than idle in the main event loop. Applications that do on-going processing should do their work only when they receive a null event.
PollSystem returns with a value of true when an event is available. The first field in the polling record is “what,” which tells your application what type of event has occurred. The following section of this chapter describes how your application should respond to each event. It also details any programming considerations that should be taken into account when responding to such an event.